#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/videodev2.h>
#include <sys/mman.h>

#define BUFFER_SIZE 1000000

//Struct to hold mmap
struct {
        void *start;
        size_t length;
} *buffers;

int main()
{
	int fd, ret,i;
	struct v4l2_capability video_cap;
	struct v4l2_pix_format * pfmt;
	struct v4l2_format video_format;
	struct v4l2_requestbuffers rbuf;
	struct v4l2_buffer buffer;
	char * userbuf;

	printf("Starting video test application...\n");
	fd = open("/dev/video0", O_RDONLY);
	if(fd == -1)
	{
		perror("Opening /dev/video0");
		return -1;
	}

	ret = ioctl(fd, VIDIOC_QUERYCAP, &video_cap);	
	if(ret == -1)
	{
		perror("IOCTL on /dev/video0");
		return -1;
	}
	printf("Driver: %s\n", video_cap.driver);
	printf("Bus: %s\n", video_cap.bus_info);
	printf("Capabilites: %08x\n", video_cap.capabilities);

	video_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	ret = ioctl(fd, VIDIOC_G_FMT, &video_format);	
	if(ret == -1)
	{
		perror("IOCTL on /dev/video0");
		return -1;
	}
	//Since this is a union, typecast the pointer
	pfmt = (struct v4l2_pix_format *)&video_format.fmt;
	printf("Width = %d\n", pfmt->width);
	printf("Height = %d\n", pfmt->height);
	printf("Format = %x\n", pfmt->pixelformat);

	//rbuf.count = 10;
	rbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	//rbuf.memory = V4L2_MEMORY_MMAP;
	rbuf.memory = V4L2_MEMORY_USERPTR;
	ret = ioctl(fd, VIDIOC_REQBUFS, &rbuf);	
	if(ret == -1)
	{
		perror("IOCTL on /dev/video0");
		return -1;
	}
	buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	buffer.memory = V4L2_MEMORY_USERPTR;
	userbuf = malloc(BUFFER_SIZE);
	buffer.m.userptr = *userbuf;
	buffer.length = BUFFER_SIZE;
	ret = ioctl(fd, VIDIOC_QBUF, &buffer);	
	if(ret == -1)
	{
		perror("IOCTL on /dev/video0");
		return -1;
	}
	printf("Complete\n");
	/*
	buffers = calloc (rbuf.count, sizeof (*buffers));
	
	//Map the buffers from the kernel using mmap
	for (i = 0; i < rbuf.count; i++) {

		memset (&buffer, 0, sizeof (buffer));
		buffer.type = rbuf.type;
		buffer.memory = V4L2_MEMORY_MMAP;
		buffer.index = i;

		if (-1 == ioctl (fd, VIDIOC_QUERYBUF, &buffer)) {
			perror ("VIDIOC_QUERYBUF");
			exit (EXIT_FAILURE);
		}

		buffers[i].length = buffer.length; // remember for munmap()
		printf("Buffer Length: %d", buffers[i].length);

		buffers[i].start = mmap (NULL, buffer.length,
					 PROT_READ | PROT_WRITE, // recommended 
					 MAP_SHARED,             // recommended
					 fd, buffer.m.offset);

		if (MAP_FAILED == buffers[i].start) {
			// If you do not exit here you should unmap() and free()
			//   the buffers mapped so far. 
			perror ("mmap");
			exit (EXIT_FAILURE);
		}
	}

	for (i = 0; i < rbuf.count; i++)
        	munmap (buffers[i].start, buffers[i].length);
	*/
	close(fd);
	return 0;
}
